Ксожалению, конструктор форм (Forms
Designer) не поддерживается в C++ Тем не менее, вы
можете использовать конструктор форм (Forms
Designer) в С#, и потом перенести полученный с
помощью С# код графического интерфейса
пользователя в программу на C++ Для переноса
графического интерфейса пользователя в
программу на C++ необходимы дополнительные
усилия, и, в большинстве случаев, такой
перенос особой пользы не дает Как правило, C++
не используют для разработки
пользовательских графических интерфейсов,
вместо этого применяется подход смешения
языков, в котором для создания
почьзовательского интерфейса используется
С#, а в других аспектах разработки проекта
из разных соображений используется C++
Поскольку вам, скорее всего, придется часто
создавать графический интерфейс
Windows Forms (Формы Windows) — это та часть каркаса .NET Framework, которая поддерживает создание приложений со стандартным графическим пользовательским интерфейсом (GUI) на платформе Windows. Среди классов Windows Forms (Формы Windows) есть обширный набор классов для создания сложных графических пользовательских интерфейсов. Эти классы можно использовать в приложениях, написанных на любом языке .NET
Рис. 6.1. Упрощенная схема иерархии классов
Windows Forms (Формы Windows)
Как правило, ваше приложение будет содержать главное окно, которое реализовано с помощью некоторого класса MyForm, производного от класса Form (Форма). На рис 6.1 изображено, какое место ваш класс MyForm занимает в иерархии классов Windows Forms (Формы Windows).
Для ознакомления с классами Windows Forms (Формы Windows) полезно будет создать простое приложение SimpleForm (Простая форма) в несколько шагов. Ни на одном из этих шагов мы не будем использовать средства проектирования Visual Studio. Используя интерфейс командной строки, необходимо запустить командный файл build. bat.
Приложение SimpleForm (Простая форма) — скелет стандартного приложения Windows. Вот код приложения SimpleForm (Простая форма), созданный на шаге 0:
//SimpleForm.срр - Шаг 0
// Эта версия отображает простую
форму (simple form)
fusing <mscorlib.dll>
fusing <System.dll>
fusing <System.Drawing.dll> // Система
fusing <System.Windows.Forms.dll> // Система
using namespace System;
// использование пространства имен
Система;
using namespace System::Windows::Forms;
// использование пространства имен
Система::Windows::Формы;
_gc class Forml : public Form
// класс сборщика мусора Forml:
общедоступная Форма
{
public:
Forml()
{
Size = // Размер
*_nogc new System::Drawing::Size(300,200); // Размер
Text = "Simple Form - Step 0";
// Текст = "Простая Форма - Шаг О";
}
static void Main()
{
Application::Run(new Forml);
// Приложение:: Выполнить (новая Forml);
}
};
int _stdcall WinMain(
long hlnstance, // дескриптор текущего
экземпляра
long hPrevInstance, // дескриптор
предыдущего экземпляра
long IpCmdLine, // командная строка
int nCmdShow // состояние отображения )
{
Forml::Main();
return 0;
}
Класс Forml является производным от
System:: Windows:: Forms:: Form (Cистема::Windows::Формы::Форма).
В классе System::Windows::Forms::Application (Система::Windows::Формы::Приложение)
есть статические методы для управления
приложением, например Run (Выполнить) и Exit (Выход).
Метод WinMain создает новую форму и запускает
ее в качестве главного окна приложения.
Обратите внимание, что в примерах
этой главы, написанных на C++, вместо имени
функции main (главная) в качестве точки входа
используется WinMain. В принципе можно в
функции main (главная) в рамках консольного
приложения реализовать все возможности
графического интерфейса пользователя. Но
при этом подходе придется создать
бездействующее консольное окно, что в
приложениях с графическим
пользовательским интерфейсом совсем ни к
чему. Если же использовать WinMain вместо main (главная),
то в программе не создаются консольные окна,
а сразу создается главное окно.
Конструктор формы инициализирует
форму. Значение в поле Size (Размер)
определяет размер формы в пикселях. Поле Text
(Текст) определяет заголовок, который
отображается в области заголовка окна
новой формы.
Ключевым классом Windows Forms (Формы
Windows) является базовый класс Form (Форма). Этот
класс содержит обширный набор функций,
которые наследуются разрабатываемыми нами
классами форм, производными от класса Form (Форма).
Чтобы создать приложение, нужно
выполнить из командной строки командный
файл build.bat. А чтобы запустить командный файл,
откройте окно DOS, перейдите в папку SimpleFormXStep(),
и введите в командной строке build (компоновка).
Помните, что . перед этим необходимо
правильно установить значения переменных
среды. Для этого достаточно выполнить Visual
Studio.NET Command Prompt.
cl /CLR SimpleForm.cpp
По умолчанию будет
откомпилирован исполняемый файл Windows. В
исходном коде приложения находятся
директивы fusing, в которых указаны
используемые библиотеки .NET:
System.dll,System.Drawing.dllи System.Windows.Forms.dll.
После того, как вы
откомпилировали приложение с помощью
командного файла, можете запустить его,
введя в командной строке SimpleForm (Простая
форма). Вы также можете запустить
приложение в проводнике Windows, дважды
щелкнув на файле SimpleForm.exe. На рис. 6.2
изображен внешний вид этого простого
приложения. И хотя приложение SimpleForm (Простая
форма) совсем примитивное, в нем заложено
множество возможностей, унаследованных
созданным нами классом, который является
производным от класса Form (Форма). Окно
приложения можно перетаскивать по экрану,
изменять его размер, свертывать,
развертывать, в нем можно открывать
системное меню (щелкнув кнопкой мыши в
верхнем левом углу окна) и т.д.
Сообщения о работе окна
В Visual Studio.NET есть инструментальное средство под названием Spy++ (Шпион++). Эта программа "шпионит" за окнами, чтобы иметь представление о том, что происходит внутри окна. Чтобы в Visual Studio запустить Spy++ (Шпион++), нужно воспользоваться меню Tools (Сервис). Запустите версию приложения SimpxeForm.exe, полученную на шаге 0, а затем запустите Spy++ (Шпион++). Выберите Spy (Шпион) Find Window (Найти окно) — появится диалоговое окно Find Window (Найти окно). В этом диалоговом окне установите переключатель Messages (Сообщения), как на рис. 6.3
Рис. 6.2. Скелет приложения \Vindowb Forms (Формы
Windows) (Шаг 0)
Рис. 6.3. Инструмент Finder Tool (Средство поиска)
служит для поиска окна — объекта шпионажа
Левой кнопкой мыши перетащите
инструмент Finder Tool (Средство поиска) (в
диалоговом окне Find window (Найти окно) этот
инструмент отображается в виде специальной
пиктограммы — перекрестия) на окно
приложения SimpleForm (Простая форма), а потом
щелкните на кнопке ОК. Теперь в окно
программы-шпиона Spy++ будут выводиться
сообщения, информирующие обо всех
взаимодействиях с окном. Окно программы-шпиона
Spy++ показано на рис. 6.4.
Чтобы обрабатывать события,
приложения Windows должны иметь специальную
структуру Операционная система Windows в ответ
на действие пользователя, например щелчок
кнопкой мыши, выбор меню или ввод символов с
клавиатуры, посылает приложению сообщение
Приложения Windows должны иметь такую
структуру, которая позволяет реагировать
на эти сообщения
Удобство создания Windows-программ с
помощью классов NET Framework состоит в том, что
программировать можно на очень высоком
уровне абстракции На шаге 0 вы уже убедились,
насколько просто создать приложение В
последующих разделах мы будем добавлять в
приложение новые основные свойства
графических пользовательских интерфейсов,
и таким образом проиллюстрируем основы
создания графических пользовательских
интерфейсов с помощью классов Windows Forms (Формы
Windows)
В приложении, созданном на первом шаге, будет показано, как отобразить на форме текст На рис. 6.5. можно увидеть, как выглядит это приложение при выполнении
Рис. 6.4. Окно Messages (Сообщения) программы Spy++(Шпион++)
Рис. 6.5. Отображение текста на простой форме
(Шаг 1)
Вывод данных в программах Windows
сильно отличается от вывода данных в
аналогичных консольных приложениях, где
для этого используется метод Console: :WriteLine
Вычерчивание результата в окне часто
называют закрашиванием или закраской
Закрашивание выполняется в ответ на
сообщение "раскрасить", WM_PAINT Такой
способ закрашивания по требованию
гарантирует, что если окно будет накрыто
каким-либо другим окном, а затем открыто
снова, то содержимое окна будет отображено
корректно
Еще одно отличие выполнения
вывода в Windows-программах от выполнения
вывода в консольных приложениях состоит в
том, что необходимо определить все детали
Например, нужно указать координаты области
рисования, "кисть", которой будет
выполняться рисование, шрифт текста, и так
далее Вот код приложения, созданного на
шаге 1
//SimpleForm.cpp - Шаг 1
// Эта версия отображает
приветствие
fusing <mscorlib.dll>
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
using namespace System;
// использование пространства имен
Система;
using namespace System::Windows:.Forms;
// использование пространства имен
Система.:Windows::Формы;
using namespace System::Drawing;
// использование пространства имен
Система::Рисование;
_gc class Forml : public Form
// класс сборщика мусора Forml:
общедоступная Форма
{
private: // частный
float x, у; // с плавающей точкой Brush *pSto<Brush;
// Кисть public:
Forml() {
Size = // Размер
*_nogc new System::Drawing::Size(300,200);
// Размер
Text = "Simple Form - Step 1";
// Текст = "Простая Форма - Шаг
1";
x = у = 10; pStdBrush = new SolidBrush(Color::Black);
// Красить::
// Черным } protected: // защищенный
virtual void OnPaint(PaintEventArgs * ppea)
{
ppea->get_Graphics()->Graphics::DrawString //
Графика
("Hello, Window Forms", Font,
// "Привет, Формы Window ", Шрифт,
pStdBrush, x, у);
}
public:
static void Main() {
Application.:Ran(new Forml);
// Приложение:: Выполнить (новая
Форма),
}
};
int _stdcall WinMain(
long hlnstance, // дескриптор текущего
экземпляра
long hPrevInstance, // дескриптор
предыдущего экземпляра
long IpCmdLine, // командная строка
int nCmdShow // состояние отображения )
{
Forml::Main();
return 0;
}
Для того чтобы рисовать с помощью
Windows Forms (Формы Windows), нужно переопределить
виртуальный метод OnPaint Класс PaintEventArgs
содержит объект Graphics в качестве свойства,
доступного только для чтения Класс Graphics,
который принадлежит пространству имен System:
-Drawing (Система Рисунок), содержит методы
рисования
Параметры метода Drawstring
В качестве стандартной кисти используется черная кисть SolidBrush
Графический пользовательский
интерфейс (GUI) управляется событиями
приложение выполняет действия в ответ на
события, вызванные пользователем, например,
на щелчок кнопкой мыши или выбор пункта
меню Каждая форма или элемент управления
имеет заранее определенный набор событий
Например, у каждой формы есть код,
обрабатывающий событие MouseDown (Кнопка мыши
нажата)
В Windows Forms (Формы Windows) применяется
модель обработки событий NET, в которой
делегаты используются для того, чтобы
связать события с обрабатывающими их
методами В классах Windows Forms (Формы Windows)
используются групповые делегаты Групповой
делегат содержит список связанных с ним
методов Когда в приложении происходит
событие, управляющий элемент возбуждает
событие, вызвав делегат для этого события
Потом делегат вызывает связанные с ним
методы
Для того чтобы добанить де iciar к
событию, в C++ используется перегруженный
оператор += Мы добавляем метод Forml_MouseDowr к
событию MouseDown (Кнопка мыши нажата)
MouseDown += new MouseEventHandler
(this, Forml_MoaseDown),
Вскоре мы увидим этот код в программе
Документацию, касающуюся событий и их обработки, можно найти в справочнике по NET Framework ( NET Framework Reference) На рис 6 6 показаны предопредепенные события, связанные с классом Form (Форма)
Событие MouseDown (Кнопка мыши нажата) является одним из предопределенных событий класса Control (Элемент управления), от которого порожден класс Form (Форма)
public: _event MouseEventHandler* MouseDown;
А вот и объявление обработчика этого события, MouseEventHandler
public _gc _delegate void MouseEventHandler(
Object* sender, // отправитель
MouseEventArgs* e
) ;
Рис. 6.6. Документация по событиям класса Form (Форма)
В качестве параметра обработчик событий получает объект класса Мои seEventArgs (производный от класса EventArgs) Свойства этого объекта доступны только для чтения и содержат информацию, связанную с данным событием
Button (Кнопка) определяет, какая кнопка была нажата, Clicks (Щелчки) определяет, сколько раз была нажата и отпущена кнопка, Свойство Delta (Дельта) является счетчиком оборотов колесика мыши; X и Y — координаты точки, в которой находился указатель в момент нажатия кнопки мышиНа шаге 2 мы внесем изменения в приложение, чтобы при щелчке любой кнопкой мыши строка с приветствием перемещалась на место щелчка На рис. 6.7 можно увидеть, что после щелчка кнопкой мыши строка действительно переместилась
Рис. 6.7. Перемещение текста по щелчку кнопкой
мыши (Шаг 2)
//SimpleForm.cpp - Шаг 2
// SimpleForm.срр - 2
// Эта версия отображает
приветствие, которое может быть перемещено
// щелчком кнопки мыши
fusing <mscorlib.dll>
fusing <System.dll>
fusing <System.Drawing dll>
fusing <System.Windows.Forms dll>
using namespace System;
// использование пространства имен
Система;
using namespace System::Windows. Forms;
// использование пространства имен
Система::Windows::Формы;
using namespace System::Drawing;
// использование пространства имен
Система:: Рисунок;
_go class Forml : public Form
// класс сборщика мусора Forml:
общедоступная Форма
{
private: // частный
void InitializeComponent()
{
MouseDown += new MouseEventHandler // новый
обработчик
// события
(this, Forml_MouseDown);
}
float x, у; // с плавающей точкой
Brush *pStdBrush; // Кисть public:
Forml()
{
InitializeComponent(); Size = // Размер
*_nogc new System::Drawing::Size(300,200); // Размер
Text = "Simple Form - Step 2"; // Текст = "Простая
Форма - Шаг 2"; x = у = 10;
pStdBrush = new SolidBrush(Color::Black) ; // Красить::Черным
}
protected- // защищенный void Forml_MouseDown
(Object *pSender, MouseEventArgs *pmea)
{
x = pmea->X; у = pmea->Y;
Invalidate(); I
}
Во время инициализации программа
связывает метод Forml_MouseDown с событием MouseDown (Кнопка
мыши нажата) Этот метод устанавливает
координаты текста, х и у, равными
координатам точки, в которой находился
указатель в момент щелчка Для того чтобы
понять роль метода Invalidate (Считать
недействительным), закомментируйте его и
снова скомпонуйте код Щелкните мышью, чтобы
перенести текст Что произойдет в
результате9 Приветствие останется на том же
месте Потом накройте окно приложения каким-либо
другим окном, а потом снова откройте его
Теперь вы увидите, что строка перемещена
Метод Invalidate (Считать
недействительным) определен в базовом
классе Control (Элемент управления) Существует
несколько переопределенных версий этого
метода Каждая из них заставляет считать
недействительной определенную область
управляющего элемента и посылает элементу
управления сообщение о перерисовывании
Метод, который не содержит параметров,
заставляет считать недействительным весь
управляющий элемент Для того чтобы
максимально уменьшить объем
перерисовывания, в более сложном
приложении можно ограничиться тем, что
недействительным будет считаться
прямоугольник
На шаге 2М создания нашего приложения мы реализуем два разных обработчика события MouseDown (Кнопка мыши нажата). Второй обработчик по щелчку кнопкой мыши просто отображает окно сообщения.
//SimpleForm.срр - Шаг 2М
// Эта версия имеет два обработчика
событий для MouseDown
_gc class Forml : public Form
// класс сборщика мусора Forml:
общедоступная Форма
{
private: // частный
void InitializeComponent()
{
MouseDown += new MouseEventHandler
(this, Forml__MouseDown) ;
MouseDown += new MouseEventHandler
(this, ShowClick);
}
void Forml_MouseDown
(Object *pSender, MouseEventArgs *pmea)
{
x = pmea->X;
у = pmea->Y;
Invalidate(); }
void ShowClick (Object *pSender, MouseEventArgs *pmea)
{
MessageBox::Show("Mouse clicked!!'");
// "Мышь щелкнула!!! }
На шаге 3 мы введем в наш пример обработку еще одного события, а именно, события KeyPress (Нажатие клавиши), а также покажем, как в событии MouseDown (Кнопка мыши нажата) различать, какая кнопка была нажата, левая или правая.
Обработка событий, вызванных правой и левой кнопкой мыши
Для того чтобы определить, какая кнопка мыши была нажата, нужно использовать свойство Button (Кнопка) параметра MouseEventArgs. Правую кнопку мыши будем использовать для удаления строки с приветствием, которая хранится в элементе данных str класса StringBuilder.
void Forml_MouseDown
(Object *pSender, MouseEventArgs *pmea)
{
if (pmea->Button == МоиseButtons::Left) // если
левая кнопка
{
x = pmea->X;
у = pmea->Y;
}
else if (pmea->Button == MouseButtons::Right) // если
правая
// кнопка
{
pStr = new StringBuilder();
}
Invalidate() ;
}
Событие Keypress (Нажатие клавиши)
На шаге 3 мы научимся обрабатывать событие KeyPress (Нажатие клавиши). Каждый раз, когда пользователь нажмет клавишу, в конец строки приветствия будет добавлен соответствующий символ. Обратите внимание, что вместо класса String (Строка) используется класс StringBuilder, который более эффективен в этой ситуации. Объект String (Строка) — стационарный (неизменяемый), то есть, для того, чтобы реализовать добавление символов в конец строки, нужно постоянно удалять одни объекты String (Строка) и создавать другие.
StringBuilder *pStr;
void Forml_KeyPress
(Object *pSender, KeyPressEventArgs *pmea)
{
pStr—>Append(pmea->KeyChar) ; // Добавляем в
конец
Invalidate() ;
}
Также, как и на шаге 2, необходимо вызвать метод Invalidate (Считать недействительным), для того, чтобы принудительно перерисовать окно приложения после сделанных изменений. На рис. 6.8 показано окно приложения SimpleForm (Простая форма), после удаления исходного текста и ввода нового.
Рис. 6.8. Испытываем события мыши и нажатия
клавиши на клавиатуре (Шаг 3)
Все пользователи Windows-приложений хорошо знакомы с меню, которые представляют собой простой механизм выбора команд. В языках .NET меню реализуется в самой программе. Иными словами, для меню файл ресурсов не нужен.
На шаге 4 мы добавим в наше приложение Simple Form простое меню Для того чтобы выйти из программы, пользователь должен выбрать File => Exit (Файл => Выход), как на рис. 6.9.
Рис. 6.9. Шаг 4 Добавление в форму меню File =>
Exit (Файл => Выход)
//SimpleForm.срр - Шаг 4
_gc class Forml : public Form
// класс сборщика мусора Forml:
общедоступная Форма
{
private: // частный
void InitializeComponent()
{
pMainMenul = new MainMenu ();
pMenuFile = new Menultem ();
pMenuExit = new Menultem ();
// mainMenul
Menultem* pMainMenulItems[] = {pMenuFile};
pMainMenul->get_MenuItems()
->AddRange(pMainMenulItems); // Меню File
pMenuFile->set_Index(0);
Menultem* pMainFileltems[] = {pMenuExit};
pMenuFile->get_MenuItems()
->AddRange(pMainFileltems);
pMenuFile->set_Text("File"); // Файл
// Меню Exit
pMenuExit->set_Index{0);
pMenuExit->set_Text("Exit"); // Выход
pMenuExit->Click += new System::EventHandler // Щелчок
(this, MenuExit_Click);
Menu = pMainMenul; // Меню
MouseDown += new MouseEventHandler
(this, Forml_MouseDown);
KeyPress += new KeyPressEventHandler
(this, Forml_KeyPress); }
float x, у; // с плавающей точкой
Brush *pStdBrush; // Кисть
StringBuilder *pStr;
Menultem *pMenuExit;
Menultem *pMenuFile;
MainMenu *pMainMenul;
public:
private: // частный
void MenuExit_Cliok(
Object *pSender, EventArgs *pea)
{
Application::Exit(); // Приложение:: Выход
}
В методе initializeComponent создается
иерархическая структура меню,
представленная экземпляром класса MainMenu (Главное
меню). Меню состоит из объектов Menultem, каждый
из которых является отдельной командой
меню Каждый объект Menultem является командой
приложения или командой родительского меню
для других пунктов подменю В нашем
приложении мы связываем объект MainMenu (Главное
меню) с объектом Form (Форма), присваивая
свойству Menu (Меню) объекта Form (Форма)
значение MainMenu (Главное меню)
Когда в этой главе мы позже
обсудим конструктор форм (Forms Designer), вы
увидите, что меню можно создать и так нужно
просто перетянуть элемент управления MainMenu (Главное
меню) с панели инструментов на форму.
Конструктор форм (Forms Designer) позаботится о
генерации нужного шаблонного кода.
Как и в случае других событий Windows Forms (Формы Windows), с событием связывается его делегат Щелчок на пункте меню приводит к выполнению соответствующей команды
void InitializeComponent()
{
pMenuExit->Click += new System::EventHandler // Щелчок
(this, MenuExit_Click);
}
void MenuExit_Click(
Object *pSender, EventArgs *pea)
{
Application::Exit(); // Приложение::Выход
}
В программе, которую мы только что рассматривали, объект pMainMenul является управляющим элементом. Данный объект — указатель на экземпляр класса MainMenu (Главное меню). Управляющий элемент — это объект на форме, который придает форме новые функциональные возможности. Управляющий элемент автоматически выполняет много заданий "по поручению" формы. Использование управляющих элементов упрощает программирование, так как программисту не надо беспокоиться о рисовании, о том, следует ли считать представление формы недействительным, не нужно думать о графических элементах и так далее. Для того чтобы реализовать простое меню с самого начала, нам пришлось написать довольно много кода. Управляющие элементы, которые реализуются с помощью объектов, содержат богатый, вполне пригодный для повторного использования код.
На шаге 5 создания приложения
SimpleForm (Простая форма) мы используем
управляющий элемент TextBox (Поле) для
отображения строки с приветствием. В более
ранних версиях приложения строку можно
было переместить щелчком левой кнопки мыши
и удалить щелчком правой кнопки мыши. Можно
было также ввести свою собственную строку с
приветствием. Теперь, применив управляющий
элемент TextBox (Поле), вы получите полноценные
возможности редактирования. Управляющий
элемент TextBox (Поле) позволяет в любом месте
строки вставить символы, вырезать и
вставить текст (с помощью комбинаций клавиш
Ctrl+X и Ctrl+V соответственно) и так далее. Все
возможности редактирования поддерживаются
управляющим элементом TextBox (Поле). На рис. 6.10
изображено окно приложения после того, как
текст приветствия был перемещен, и мы ввели
некий собственный текст.
Это новая версия программы.
Обратите внимание на то, что она
значительно проще предыдущей, хотя и имеет
гораздо более богатые функциональные
возможности. Нет больше необходимости
использовать переменные экземпляра для
координат и текста строки приветствия (теперь
эта информация хранится в управляющем
элементе pTxtGreeting типа TextBox (Поле)). Не нужен
больше метод OnPaint, так как управляющий
элемент TextBox (Поле) знает, как нарисовать
себя. Можно также избавиться от кисти.
Теперь не нужно обрабатывать событие KeyPress (Нажатие
клавиши), потому что оно автоматически
обрабатывается управляющим элементом TextBox (Поле),
притом весьма аккуратно.
Рис. 6.10. Шаг 4: текст приветствия
отображается с помощью управляющего
элемента Text Box (Поле)
//SimpleForm.cpp - Шаг 5
_gc class Forml : public Form
// класс сборщика мусора Forml:
общедоступная Форма
{
private: // частный
void InitializeComponent()
{
// текст приветствия (text greeting)
pTxtGreeting = new TextBox; pTxtGreeting->Location = //
Местоположение
* _nogc new Point(10, 10); // новая точка
pTxtGreeting->Size = // Размер
(*_nogc new struct Size(150, 20)); // новый Размер
pTxtGreeting->Text = "Hello, Windows Forms"; // Текст = "Привет,
Формы Windows";
Controls->Add(pTxtGreeting); // Добавить
}
float x, у; // с плавающей точкой
Brush *pStdBrush; // Кисть
Menultem *pMenuExit;
Menultem *pMenuFile;
MainMenu *pMainMenul;
TextBox *pTxtGreeting;
protected: // защищенный void Forml_MouseDown
(Object *pSender, MouseEventArgs *pmea) {
if (pmea->Button == MouseButtons::Left)
// если кнопка левая
{
pTxtGreeting->Location = // Местоположение
*_nogc new Point(pmea->X, pmea->Y); // новая
точка }
else if (pmea->Button == MouseButtons::Right) // если
кнопка правая {
pTxtGreeting->Text = ""; // Текст } }
};
Управляющий элемент TextBox (Поле) удобен в использовании. В инициализирующей части программы мы создаем объект TextBox (Поле) и определяем значения его свойств Location (Местоположение), Size (Размер) и Text (Текст). Мы добавляем новый управляющий элемент к коллекции управляющих элементов Controls (Управляющие элементы) этой формы. В обработчике событий мыши мы перемещаем управляющий элемент, изменив значение свойства Location (Местоположение). С помощью свойства Text (Текст) управляющего элемента TextBox (Поле) можно удалить строку с приветствием.
И хотя вполне реально создать приложение Windows Forms (Формы Windows), используя в командной строке только комплекс инструментальных средств разработки программ .NET Framework SDK, на практике подобную работу намного проще выполнить с помощью Visual Studio.NET. К сожалению, в Visual Studio.NET нет средств для генерирования проекта пусковой системы на управляемом C++ на основе Form (Форма), и управляемый C++ не поддерживает конструктор форм (Forms Designer). Однако для начала можно создать проект Windows-приложения на С# (Windows Application). При этом будет сгенерирован код пусковой системы и будут установлены ссылки на необходимые библиотеки .NET. Затем можно в конструкторе форм (Forms Designer) перетащить управляющие элементы с инструментальной панели на вашу форму. Конструктор форм (Forms Designer) вставит необходимый шаблон кода на С#, который поддерживает функционирование этих управляющих элементов в форме. В окне Properties (Свойства) несложно определить свойства управляющего элемента в процессе проектирования. Можно, конечно, определить эти свойства и во время запуска приложения, как мы это сделали для поля pTxtGreeting в предыдущем примере. После этого можно перенести код С# в программу на управляемом C++, но этого обычно не рекомендуется делать.
Лучший способ научиться
создавать приложения Windows с помощью Visual
Studio.NET — самостоятельно с самого начала
создать небольшое приложение на С#. Для
примера мы создадим Windows-приложение,
которое позволит вносить деньги на счет и
снимать деньги со счета в банке.
1. Создайте на СП новый проект Windows
Application (Windows-приложение), как на рис. 6.11, и
назовите его BankGui.
Рис. 6.11. Создание проекта Windows Application (Windows-приложение)
2. Раскройте панель инструментов
Toolbox, перетянув указатель мыши на
вертикальную вкладку Toolbox в левой части
главного окна Visual Studio. Если вкладки нет,
инструментальную панель Toolbox можно открыть
из меню ViewOToolbox (Вид1^ Панель инструментов).
Чтобы панель инструментов Toolbox оставалась
открытой, щелкните на "канцелярской
кнопке", которая находится в заголовке
панели инструментов Toolbox рядом с X. Если
курсор мыши навести на "канцелярскую
кнопку", появится подсказка с надписью
"Auto Hide" (Автоматическое свертывание).
3. Перетащите из панели
инструментов Toolbox две надписи (Label), два поля
(TextBox) и две кнопки (Button) на форму (рис. 6.12).
Рис. 6.12. Перетаскивание управляющих
элементов с панели инструментов Toolbox() на
форму
4. В конструкторе форм (Forms Designer) щелкните на надписи labell. Тем самым вы выделите этот управляющий элемент в окне Properties (Свойства), которое находится под Solution Explorer (Поиск решения). Окно Properties (Свойства) позволяет изменять свойства управляющих элементов. В поле свойства Text (Текст) объекта labell введите Amount (Сумма). После того, как вы ввели значение, нажмите возврат каретки. Вы увидите, что текст появится на форме. На рис. 6.13 показано окно Properties (Свойства) после изменения свойства Text (Текст) первой надписи.
Рис. 6.13. Изменение значений свойств в окне
Properties (Свойства)
5. Точно так же измените текст
надписи 1аЬе12 на Balance (Баланс).
6. Введите значения свойств полей
и кнопок в соответствии с табл. 6.1.
7. С помощью маркеров размера,
которые находятся посредине каждой стороны
формы, измените ее размер. При желании,
перетащите управляющие элементы на
выбранные места, и измените их размер. Если
внешний вид формы вас удовлетворяет,
сохраните изменения, сделанные в проекте.
Ваша форма должна выглядеть примерно так,
как на рис. 6.14.
8. Добавьте обработчики событий
кнопок, дважды щелкнув на каждой кнопке.
9. Добавьте необходимый код к коду,
сгенерированному мастером:
Таблица 6.1. Значения свойств полей
(Textbox) и кнопок (Button)
Имя свойства | Текст |
txtAmount | (не заполняется) |
txtBalance | (не заполняется) |
cmdDeposit | Deposit (Вклад) |
cmdWithdraw | Withdraw (Снять) |
Рис. 6.14 Форма приложения BankGui
public class Forml : System.Windows.Forms.Form
// общедоступный класс Forml:Система.Windows.Формы.Форма
{
public Forml()
{
//
// Требуется для поддержки Windows Form
Designer
//
InitializeComponent();
//
// TODO: Добавьте любой код
конструктора после
// вызова InitializeComponent
//
txtAmount.Text = "25";
// Текст txtBalance.Text = "100";
// Текст
}
/// <summary>
/// The main entry point for the application.
/// Основная точка входа для
приложения.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Forml{));
}
private void cmdDeposit_Click(object sender,
System.EventArgs e)
{
int amount = Convert.Tolnt32(txtAmount.Text);
int balance = Convert.Tolnt32(txtBalance.Text); // баланс
balance += amount;
// баланс + = количество;
txtBalance.Text = Convert.ToString(balance); // Текст
}
private void cmdWithdraw_Click(object sender,
System.EventArgs e)
{
int amount = Convert.Tolnt32(txtAmount.Text);
int balance = Convert.Tolnt32(txtBalance.Text); // баланс
balance = amount;
txtBalance.Text = Convert.ToString(balance); // Текст
}
10. Откомпилируйте и выполните приложение. Оно должно вести себя как стандартное приложение Windows. Вы должны без проблем вносить деньги на счет и снимать деньги со счета. На рис. 6.15 показано выполняющееся приложение BankGui.
Рис. 6.15. Windows-приложение BankGui
В данный момент проект реализован
на С#. И хотя этого, как правило, не делают, мы
перенесем этот проект в C++ для того, чтобы
показать, как это нужно делать. Сначала с
помощью шаблона Managed C++ Empty Project (Пустой
проект на управляемом C++) создадим новый
проект C++, который назовем BankGuiPort.
Теперь создадим исходный файл
Forml.cpp в проекте BankGuiPort и перенесем (с помощью
команд сору (копировать) и paste (вставить)) код
С# из исходного файла Forml. cs проекта BankGui.
Перенесите все строки кода из
файла Forml.cs проекта BankGui в файл Forml.cpp проекта
BankGuiPort. При таком переносе кода могут
возникнуть проблемы и непредвиденные
ситуации. Эти проблемы не будут рассмотрены
в нашей книге и вам придется ознакомиться с
ними самостоятельно, если вы и в дальнейшем
захотите выполнять подобный перенос кода.
Итак, откройте оба проекта — BankGui на С# и
BankGuiPort на C++ — в двух копиях Visual Studio.NET и
визуально сравните исходные файлы Forml.cs и
Forml.cpp, чтобы получить представление о
подробностях переноса кода.
//Form1.cpp
#using <mscorlib.dll>
#using <System.dll>
#using <System.Drawing.dll>
#using <Systern.Windows.Forms.dll>
using namespace System;
// использование пространства имен
Система;
namespace BankGui
// пространство имен BankGui
{
_gc class Forml : public System::Windows::Forms::Form
// класс сборщика мусора Forml:
общедоступная Система::
// Windows:: Формы:: Форма
{
private: // частный
System::Windows: Forms::Label *label1;
System::Windows: Forms::Label *labe!2;
System::Windows: Forms::TextBox *txtAmount;
System::Windows: Forms::TextBox *txtBalance;
System::Windows: Forms::Button *cmdDeposit; // Кнопка
System::Windows: Forms::Button *cmdWithdraw; // Кнопка
System::ComponentModel::Container *components; //
Контейнер
public:
Form1 ()
{
components =0; // компоненты
InitializeComponent();
txtAmount->Text = "25"; // Текст
txtBalance->Text = "100"; // Текст
}
private: // частный
void InitializeComponent()
{
cmdWithdraw = new System: :Windows::Forms::Button;
// Кнопка
cmdDeposit = new System::Windows::Forms::Button;
// Кнопка
txtBalance = new System::Windows::Forms::TextBox;
txtAmount = new System::Windows::Forms::TextBox;
labell = new System::Windows::Forms::Label; // Надпись
Iabel2 = new System: : Windows :: Forms :-.Label; //
Надпись
SuspendLayout();
//
// cmdWithdraw
//
cmdWithdraw->Location = // Местоположение
* _nogc new System::Drawing::Point(152, 144);
// Точка
cmdWithdraw->Name = "cmdWithdraw"; // Имя
cmdWithdraw->TabIndex = 2;
cmdWithdraw->Text = "Withdraw"; // Текст =
"Снять"
cmdWithdraw->Click += // Щелчок
new System::EventHandler(this, cmdWithdraw_Click);
//
// Form1
//
AutoScaleBaseSize =
* _nogc new System::Drawing::Size(5, 13);
// Размер
ClientSize =
* _nogc new System::Drawing::Size(280, 189);
// Размер
System: :Windows::Forms::Control* pltems[] = {
cmdDeposit,
txtAmount,
label1,
label2,
txtBalance,
cmdWithdraw};
Controls->AddRange(pltems);
"Name = "Forml"; // Имя
Text = "Forml"; // Текст
Load += new System::EventHandler(this, Forml_Load);
ResumeLayout(false); // ложь } void Forml_Load(
Object *sender, System::EventArgs *e)
{
}
void cmdWithdraw_Click(
Object *sender, System::EventArgs *e)
{
int amount = Convert::ToInt32(txtAmount->Text);
// преобразование текста
int balance = Convert::ToInt32(txtBalance->Text);
// преобразование текста
balance -= amount;
// -количество
txtBalance->Text = Convert::ToString(balance);
// преобразование в текст }
public:
[STAThread] static void Main()
{
System::Windows::Forms::Application::Run(new Forml);
// Приложение:: Выполнить (новая Forml);
}
};
}
Окно конструктора (Design window) и окно кода (Code window)Для работы с проектами Windows Forms (Формы
Windows) в Visual Studio очень важно научиться
переключаться между окном конструктора (Design
window), где вы работаете с управляющими
этементами на форме, и окном кода (Code window),
где вы работаете с кодом программы Мы можем
показать это на примере двух окон проекта
VsForm на С#, код стартовой системы этого
проекта находится в папке VsForm\Stepl главной
папки данной главы Версия этого проекта,
перенесенная из С# на C++, находится в папке
VsFormPortXStepl Это первая версия проекта
стартовой системы, которая отображает одну
и ту же строку приветствия Проекты,
отвечающие разным стадиям разработки,
последовательно пронумерованы, и каждой
версии проекта на С# (они содержатся в папке
VsForm), созданной с помощью конструктора форм
(Forms Designer), соответствует перенесенная
версия проекта на C++, которая содержится в
папке VsFormPort
|
1. Скомпонуйте и выполните
программы (стартовые системы) на С# и C++,
находящиеся в папках VsForm\Stepl и VsFormPortXStepl, и
убедитесь, что они работают одинаково Это
полностью статические приложения, — они
просто отображают строку приветствия в
фиксированной позиции
2. Откройте форму проекта VsForm\Stepl в
окне конструктора (Design window) и щелкните на
кнопке Events (События) в окне Properties (Свойства)
3. Найдите событие MouseDown (Кнопка
мыши нажата), как на рис. 6.18.
4. В окне Properties (Свойства) дважды
щелкните на событии MouseDown (Кнопка мыши
нажата) Автоматически будет сгенерирован
код, который зарегистрирует делегата для
события и образует скелет метода,
связанного с делегатом
Рис. 6.17. Окно кода (Code window) в проекте Windows Forms (Формы
Windows)
private void InitializeComponent ()
{
this.MouseDown =
new System.WinForms.MouseEventHandler
(this.Forml_MouseDown);
}
protected void Forml_MouseDown (object sender,
System.WinForms.MouseEventArgs e)
{
}
Рис. 6.18. Добавление события с помощью кнопки
Events (События)
1. Чтобы установить координаты строки приветствия, добавьте код в обработчик события мыши (нажатие кнопки мыши) Не забудьте после этого вызвать метод Invalidate (Считать недействительным)
protected void Forml_MouseDown (object sender,
System WinForms.MouseEventArgs e)
{
x = e X;
у = e Y;
Invalidate() ;
}
2. Скомпонуйте и выполните проект
Теперь по щелчку мыши (любой кнопкой)
приветствие должно перемещаться Проект
сейчас находится на шаге 2 разработки и
соответствует проекту, хранящемуся в папке
VsForm\Step2
Вместо того, чтобы переносить
каждую строчку кода, созданного на СП, в
файл Forml cpp проекта VsForm\Step2, просто сделайте
копию проекта VsFormPortXStepl, который уже получен
с помощью переноса кода Потом перенесите
несколько строчек кода, связанных с
событием MouseDown (Кнопка мыши нажата) из VsForm\Step2
void InitializeComponent()
{
MouseDown +=
new System::Windows::Forms:-MouseEventHandler
(this, Forml_MouseDown);
}
void Forml_MouseDown (Object *sender,
System::Windows::Forms::MouseEventArgs *e)
{
x = (float)e->X; // с плавающей точкой
у = (float)e->Y; // с плавающей точкой
Invalidate();
}
3. Откройте панель инструментов
Toolbox, если она до сих пор еще не открыта (щелкните
на ярлыке панели инструментов Toolbox в
вертикальной линейке) и перетащите
управляющий элемент MainMenu (Главное меню) на
форму приложения.
4. Для создания выпадающего меню
File (Файл) с пунктом Exit (Выход), введите File (Файл)
и Exit (Выход), как на рис. 6.19.
Рис. 6.19. Использование управляющего
элемента Menu (Меню) для добавления в форму
меню
5. В окне Properties (Свойства) измените
названия этих пунктов меню на menuFile и menuExit.
6. Дважды щелкните на Exit (Выход),
чтобы добавить код в обработчик события File
=> Exit (Файл => Выход).
7. Добавьте в обработчик код,
закрывающий приложение.
protected void menuExit_Click (object sender,
System.EventArgs e)
{
Application.Exit(); // Приложение.Выход
}
8. Скомпонуйте и выполните
приложение. Меню должно полностью работать.
Полученный проект соответствует проекту,
который находится в папке VsForm\Step3.
И снова, вместо того, чтобы
переносить каждую строчку кода, созданного
на С#, из файла Forml.cpp проекта VsForm\step3 в проект
на C++, просто сделайте копию проекта VsFormPort\Step2,
созданного ранее с помощью переноса кода.
Потом перенесите те несколько строчек кода,
которые связаны с новыми функциями меню, из
VsForm\Step3.
// VSForm - Step3
_gc class Forml : public System::Windows::Forms::Form
{
private: // частный
float x, у; // с плавающей точкой
Brush *pStdBrush; // Кисть
System: -.Windows: : Forms : :MainMenu *mainMenul;
System::Windows::Forms::MenuItem *menuFile;
System::Windows::Forms::MenuItem *menuExit;
private: // частный
void InitializeComponent()
{
menuFile =
new System: -.Windows: : Forms: :MenuItem() ; menuExit =
new System::Windows::Forms::MenuItem(); mainMenul =
new System::Windows::Forms::MainMenu() ;
//
// menuFile
//
menuFile->Index =0; // Индекс
System::Windows::Forms::MenuItem *pltems[] =
{menuExit};
menuFile->MenuItems->AddRange(pltems) ;
menuFile->Text = "File"; // menuFile->
Текст = "Файл";
//
// menuExit
//
menuExit->Index = 0;
// Индекс menuExit->Text = "Exit";
// menuExit-> Текст = "Выход";
menuExit->Click += // Щелчок
new System::EventHandler
(this, menuExit_Click);
//
// mainMenul
// System::Windows::Forms::MenuItem *pMenus[] =
{menuFile};
mainMenul->Menu!tems->AddRange(pMenus);
//
// Forml
// AutoScaleBaseSize =
* _nogc new System::Drawing::Size(5, 13);
// Размер ClientsTze =
* _nogc new System::Drawing::Size(248, 181);
// Размер Menu = mainMenul;
}
private: // частный
void menuExit_Click(
Object *sender, System::EventArgs *pe)
{
Application::Exit(); // Приложение:: Выход
}
};
Давайте сделаем так, что каждый раз, когда пользователь попытается закрыть приложение, приложение будет его спрашивать, действительно ли он хочет выйти Существует несколько способов закрыть окно-
щелкнуть на кнопке "X" (Закрыть) в правом верхнем углу окна; закрыть окно из системного меню в левом верхнем углу окна, закрыть окно с помощью комбинации клавиш AU+F4, выйти из приложения с помощью меню FileOExit (ФайлОВыход)Когда закрывается форма, вызывается событие Closing (Процедура завершения) Можно остановить процедуру завершения, установив в обработчике этого события свойство Cancel (Отмена). (Сначала нужно, как обычно, добавить обработчик события Closing (Процедура завершения) ) Просто напечатайте код MessageBox (Окно сообщения), приведенный ниже
protected void Forml_Closing (object sender.
System.ComponentModel.CancelEventArgs e)
{
DialogResult status = MessageBox.Show( // состояние
"Do you want to close",
// "Хотите закрыть?",
"Simple Form (VS)", MessageBoxButtons.YesNo);
if (status == DialogResult.No)
// если (состояние == DialogResult. Нет)
{
e.Cancel = true; // Отмена = истина
}
}
Для того чтобы получить нужное нам поведение приложения, обработчик меню FileOExit (ФайлОВыход) должен не выходить из приложения, а закрыть главное окно, вызвав метод С lose (Закрыть)
protected void menuExit_Click (object sender,
System.EventArgs e)
{
//Application.Exit();
// Приложение.Выход ();
Close () ;
}
Теперь проект соответствует проекту, находящемуся в папке VSForm\Step4 Запустите программу, и попытайтесь закрыть окно приложения разными способами В любом случае должно появиться диалоговое окно, показанное на рис. 6.20.
Рис. 6.20. Диалоговое окно, которое спрашивает
пользователя, действительно ли он хочет
закрыть приложение
И, наконец, как обычно, перенесите код проекта, подготовленного на С#, в проект на C++ VSFormPort\Step4. Скомпонуйте и выполните программу на C++. Убедитесь в том, что она работает так же, как и программа на С#
// VSForm - Step4
_gc class Forml : public System:-.Windows :: Forms :: Form
{
private: // частный
void InitializeComponent()
{
Closing += // Закрытие
new CancelEventHandler(this, Forml_Closing) ;
}
void menuExit_Click(
Object *sender, System::EventArgs *pe)
{
//Application::Exit();
// Приложение:: Выход ()
; Close();
}
void Form1_Closing(
Object *sender, CancelEventArgs *e)
{
int status = MessageBox::Show( // состояние
"Do you want to close",
// "Хотите закрыть",
"Simple Form (VS)", // Простая Форма
MessageBoxButtons::YesNo);
if (status == DialogResult::No)
// если (состояние == DialogResult::No)
{
e->Cancel = true; // Отмена = истина
}
}
};
Все оставшиеся примеры в этой главе написаны исключительно на С#!
Далее в этой главе мы будем рассматривать только программы на С#, поскольку даже в программах, которые в основном написаны на C++, при разработке графических пользовательских интерфейсов, как правило, используется С#. Причина этого проста— в C++ не поддерживается конструктор форм (Forms Designer). Всегда помните о том, что вы можете сначала создать графический пользовательский интерфейс на С#, а потом, если понадобится, перенести этот код в C++. В предыдущих примерах мы показали, как это сделать.
Использование диалоговых окон
облегчает процесс взаимодействия
пользователя с приложением Windows Диалоговое
окно — это набор управляющих элементов, с
помощью которых упрощается процесс ввода
данных В предыдущем примере было описано,
как создать простое диалоговое окно,
которое позволяло бы пользователю на
вопрос дать ответ "Да" или "Нет"
Для создания таких диалоговых окон
используется класс MessageBox (Окно сообщения)
Более сложные диалоговые окна создаются на
основе форм.
Мы проиллюстрируем создание
диалоговых окон на примере графического
пользовательского интерфейса для бюро
путешествий Acme (Acme Travel Agency) Код примера, как
обычно, находится в папке CaseStuay для этой
главы Давайте рассмотрим простой диалог, с
помощью которого можно добавить гостиницу
в список гостиниц. Скомпонуйте и запустите
пример В главной форме щелкните на кнопке Add...
(Добавить ) После этого появится диалоговое
окно New Hotel (Новая гостиница), которое
показано на рис. 6.21.
Рис. 6.21. Диалоговое окно для добавления
новой гостиницы
Теперь пользователь может
вводить данные. Щелчок на кнопке ОК.
приведет к тому, что информация будет
запомнена Щелчок на кнопке Cancel (Отмена)
приведет к тому, что данные будут
проигнорированы. Это диалоговое окно, так
же как и окно сообщения, является модальным
Если модальное диалоговое окно открыто, то
пользователь может взаимодействовать с
приложением только через это окно, — ни с
какими иными средствами приложения он
взаимодействовать не может. Если вы
попытаетесь сделать что-нибудь на главной
форме, когда открыто диалоговое окно New Hotel (Новая
гостиница), то услышите гудок. Существуют
также и немодальные диалоговые окна,
которые позволяют взаимодействовать с
иными средствами приложения даже тогда,
когда немодальное диалоговое окно открыто.
Если рассматривать диалоговое
окно как форму, то обычно у него есть свои
специфические характеристики. Как правило,
у диалоговых окон нет системного меню, нет
кнопок свертывания Minimize (Свернуть) и
развертывания Maximize (Развернуть), причем
размер окна фиксирован Вы можете наблюдать
эти свойства на примере диалога New Hotel (Новая
гостиница).
Для того чтобы продолжить
испытание программы, введите данные о новой
гостинице и щелкните на кнопке ОК.
Программа вернет вас в главную форму, где
новая гостиница будет отображена в списке
гостиниц (рис. 6 22). На главной форме
реализованы также и другие управляющие
элементы графического интерфейса
пользователя, например, окно, в котором
отображается список гостиниц, а также
многострочное текстовое поле для
отображения текста, который не помещается в
одну строку.
Рис. 6.22. Главная форма для управления
гостиницами
Диалоговые окна очень хорошо описаны в документации по комплексу инструментальных средств разработки программ .NET Framework SDK Информацию по диалоговым окнам следует искать в подразделе "Dialog Boxes in Windows Forms" ("Диалоговые окна в Формах Windows") раздела "Introduction to Windows Forms" ("Введение в Формы Windows") Следует заметить, что во всех языках .NET принципы работы диалоговых окон одни и те же Это является серьезным отличием программирования на NET от традиционного программирования на Visual Basic и программирования с применением библиотеки базовых классов Microsoft (Microsoft Foundation Classes, MFC), где принципы создания диалоговых окон совершенно разные На рис. 6.23. показано, где искать документацию по диалоговым окнам
Рис. 6.23. Документация по диалоговым окнам в
NET Framework
Мы продемонстрируем детали реализации диалогового окна на примере создания диалога для изменения информации о гостинице в упрощенной версии нашего примера Код системы запуска нашего примера имеется в папке HotelAdminNStepl, которая находится в главной папке этой главы Окончательная версия программы находится в папке HotelAdmin\Step3 Можно запустить первую версию примера, а можно сразу запустить решение Step 3 и посмотреть, как должно выглядеть диалоговое окно в окончательной версии В главной форме выберите гостиницу, щелкнув на соответствующем элементе списка гостиниц Затем щелкните на кнопке Change (Изменить ) В результате появится диалоговое окно Change Hotel Information (Изменение информации о гостинице), показанное на рис. 6.24 Обратите внимание на то, что поля City (Город) и Hotel Name (Название гостиницы) недоступны Эти поля доступны только для чтения, и их значения изменить нельзя Пользователь может изменить только значения полей Rooms (Количество номеров) и Rate (Стоимость)
Создание модального диалога
В первой части нашей демонстрации
мы научим вас создавать модальное
диалоговое окно Мы покажем, как
устанавливать свойства диалога и как
возвращать результаты после щелчка на
кнопке (Ж или Cancel (Отмена)
1. Скомпонуйте и запустите
стартовую систему приложения Кнопки Add (Добавить
) и Delete (Удалить) работают, но для кнопки Change (Изменить
) имеется только заглушка, которая по щелчку
на этой кнопке отображает пустую форму Это
обычная форма Ее размер можно изменять, у
нее есть системное меню, кнопки свертывания
Minimize (Свернуть) и развертывания Maximize (Развернуть)
2. Откройте файл ChangeHotelDialog. cs в
режиме Design (Конструктор) В окне Properties (Свойства)
установите значение свойства FormBorderStyle
равным FixedDialog
3. Установите значение свойств
ControlBox, MinimizeBox и MaximizeBox равным False (Ложь)
Сейчас можно скомпоновать и запустить
приложение Теперь размер диалогового окна
будет фиксированным, у него не будет
системного меню, а в правом верхнем углу
окна не будет кнопки "X", с помощью
которой можно закрыть окно.
Рис. 6.24. Диалоговое окно для изменения
информации о гостинице
4. Теперь необходимо определить
надписи и текстовые поля, содержащие
информацию о гостинице Кроме того,
необходимо добавить кнопки ОК и Cancel (Отмена)
Когда вы будете добавлять эти управляющие
элементы, вы можете еще раз
попрактиковаться в работе с панелью
инструментов Toolbox (Инструментальная панель)
Вы можете выбрать и другой подход
скопировать эти свойства из файла NewHotelDialog.cs
и затем вставить их, для этого нужно открыть
оба файла в режиме Design (Конструктор)
5. Если вы использовали
копирование и вставку, то у управляющих
элементов свойства Name (Имя) и Text (Текст) уже
определены правильно. В противном случае
установите значения в соответствии с табл.
6.2.
6. Значение свойства Readonly для txtCity
и txtHotelName установите равным true (истина).
7. Измените размер формы так, чтобы
на ней помещались все добавленные
управляющие элементы.
8. Установите значение свойства
DialogResult кнопки ОК равным ОК. Точно так же
установите значение этого свойства кнопки
Cancel (Отмена) равным Cancel (Отмена). Сохраните
изменения, сделанные в файле ChangeHotelDialog. cs.
9. В файле MainAdminForm.cs временно
добавьте к обработчику cmdChange_Click код,
который отвечает за отображение в
текстовом поле Messages (Сообщения) строк "ОК"
и "Cancel" ("Отмена") в зависимости
оттого, как был закрыт диалог: с помощью
кнопки ОК или Cancel (Отмена). Обратите
внимание на то, что диалоговое окно
отображается с помощью метода ShowDialog, а не
метода Show (Показать), который используется
для обычных форм. В качестве результата
метод ShowDialog возвращает перечисление типа
DialogResult.
private void cmdChange_Click(object sender,
System.EventArgs e)
{
ChangeHotelDialog dig = new ChangeHotelDialog();
DialogResult status = dig.ShowDialog(); // состояние
if (status == DialogResult.OK)
// если (состояние == DialogResult. OK)
{
txtMessages.Text = "OK"; // Текст
}
else
{
txtMessages.Text = "Cancel";
// txtMessages. Текст = "Отмена";
}
}
Таблица 6.2. Значения свойств текстовых полей и кнопок диалога ChangeHotelDialog.cs
Имя (Name) | Текст |
txtCity | (не заполнено) |
txtHotelName | (не заполнено) |
txtlMumberRooms | (не заполнено) |
txtRate | (не заполнено) |
cmdOk | ОК |
cmdCancel | Cancel (Отмена) |
10. Скомпонуйте и запустите пример. Теперь диалоговое окно уже можно открыть с помощью меню, а закрыть— с помощью любой из кнопок ОК или Cancel (Отмена), причем на экран будет выведено соответствующее сообщение. Можно проверить, что диалоговое окно является модальным, пощелкав мышью где-нибудь еще в приложении. Программа сейчас находится на шаге 2 разработки.
Передача информации между родительской формой и диалогом
Во второй части нашей
демонстрации будет показано, как
передавать информацию из родительской
формы диалогу и как получать информацию от
диалога. Для этих целей в классах .NET Framework
нет встроенного механизма, но все-таки
существует некоторый шаблон
проектирования, которому можно следовать. В
классе диалога для каждого сообщения (порции
информации), которое может передаваться
между родительской формой и диалогом, нужно
определить некоторое свойство.
В нашем примере мы сделаем
свойства City (Город) и HotelName (Название
гостиницы) доступными только для записи, а
свойства Rate (Стоимость) и NumberRooms —
доступными для чтения и записи.
1. Для того чтобы реализовать
указанные свойства, добавьте к классу
Chan-geHotelDialog в файле ChangeHotelDialog. cs приведенный
ниже код.
public string City
// общедоступный строковый - Город
{
set
{
txtCity.Text = value; // txtCity. Текст = значение;
}
}
public string HotelName // общедоступная
строка HotelName
{
set
{
txtHotelName.Text = value; // txtHotelName. Текст =
значение;
}
}
public int NumberRooms
{
get
{
return Convert.ToInt32 (txtNumberRooms.Text);
}
set
{
}
}
public decimal Rate // общедоступная
десятичная Цена
{
get
{
return Convert.ToDecimal(txtRate.Text);
}
set
{
txtRate.Text = value.ToString(); // Текст =
значение
}
}
2. Теперь, чтобы установить эти свойства перед вызовом диалогового окна, и для того, чтобы использовать эти свойства перед закрытием диалогового окна с помощью кнопки ОК., добавьте код в главную форму MainAdminForm.cs. Удалите или закомментируйте временно вставленный ранее код, который отображает строки "ОК." или "Cancel" ("Отмена") в поле Messages (Сообщения).
private void cmdChange_Click(object sender,
System.EventArgs e)
{
ChangeHotelDialog dig = new ChangeHotelDialog();
if (currHotel.HotelName != "")
{
dig.City = currHotel.City; // Город
dig.HotelName = currHotel.HotelName;
dig.NumberRooms = currHotel.NumberRooms; d
ig.Rate = currHotel.Rate;
}
else
{
MessageBox.Show("Please select a hotel",
// "Пожалуйста, выберите
гостиницу ",
"Hotel Broker Administration",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation // Восклицательный
знак
) ;
return;
}
DialogResult status = dig.ShowDialog(); // состояние
if (status == DialogResult.OK)
// если (состояние == DialogResult. OK)
{
string comment = hotelBroker.ChangeRooms( // строковый
// комментарий
currHotel.City, // Город
currHotel.HotelName,
dig.NumberRooms,
dig.Rate);
if (comment == "OK")
// если (комментарий == "OK")
{
ShowHotelList(hotelBroker.GetHotels(;) ;
txtMessages.Text = "Hotel " + currHotel.HotelName
// txtMessages. Текст = "Гостиница"
// + currHotel. HotelName
+ " has been changed";
// + " была изменена";
}
else
txtMessages.Text = comment; // Текст =
комментарий
}
}
Структура currHotel содержит поля
гостиницы, выбранной в данный момент в
качестве элемента списка. В следующем
разделе вы научитесь извлекать информацию
из элемента списка и заполнять элемент
списка.
3. Скомпонуйте и испытайте
программу. Все функции диалога должны
работать корректно. Полученный проект
соответствует проекту HotelAdmin\Step3.
Управляющий элемент ListBox (Список элементов)В .NET Framework поддерживается
несколько управляющих элементов, с помощью
которых можно отобразить списки элементов.
Эти управляющие элементы позволяют
пользователю выбрать элемент списка;
обычно для выбора элемента требуется
щелкнуть на нем. В этом разделе мы
рассмотрим управляющий элемент ListBox (Список
элементов).
|
При запуске программы HotelAdmin в процессе инициализации конструктор формы MainAdminForm осуществляет начальную загрузку списка элементов listHotels, — в него загружается список гостиниц.
public MainAdminForm()
{
//
// Требуется для поддержки
конструктора форм Windows
// (Windows Form Designer)
//
InitializeComponent();
//
// TODO: Добавьте любой код
конструктора после
// вызова InitializeComponent
//
hotelBroker = new HotelBroker();
ShowHotelList(hotelBroker.GetHotels()
};
}
Метод ShowHotelList отображает в списке элементов список массивов, в которых хранится информация о гостиницах. Чтобы получить список массивов, вызывается метод HotelBroker . GetHotels. Ниже приведен метод ShowHotelList.
private void ShowHotelList(ArrayList array) // массив
{
listHotels.Iterns.Clear();
if (array == null)
// если (массив == пустой указатель)
{
return; }
foreach(HotelListltem hotel in array) // гостиница в
массиве
{
string city = hotel.City.Trim();
// строковый город = гостиница.Город.Вырезка();
string name = hotel.HotelName.Trim();
// строковое название = гостиница.HotelName.Вырезка();
string rooms = hotel.NumberRooms.ToString(); //
гостиница
string rate = hotel.Rate.ToString();
string str = city + "," + name + ","
// строка str = город +,"" +
название +,""
+ rooms + "," + rate;
listHotels.Items.Add(str); // Добавить элементы
}
}
Управляющий элемент ListBox (Список элементов) содержит свойство Items (Элементы), которое поддерживает коллекцию объектных ссылок. Сначала мы вызываем метод Items.Clear (Элементы.Очистить), чтобы очистить список элементов от тех элементов, которые отображаются в нем в момент вызова метода. Потом мы с помощью цикла перебираем гостиницы в списке массивов и создаем строку, которая состоит из полей структуры гостиницы, разделенных запятыми. Чтобы добавить эту строку в список элементов, вызывается метод Items .Add (Элементы.Добавить).
Чтобы в списке элементов выбрать какой-нибудь элемент, нужно щелкнуть на нем. Выбор элемента вызовет событие SelectedlndexChanged. Доступ к выбранному элементу можно получить с помощью свойств Selectedlndex и Selectedltem. Если никакой элемент не выбран, значение Selectedltem будет равно -1. Ниже приведен код обработчика события SelectedlndexChanged.
private void listHotels_Selected!ndexChanged(object sender,
System.EventArgs e) {
if (listHotels.Selectedlndex != -1)
{
string selected - (string) listHotels.Selectedltem;
// выбранная строка
char [ ] sep = new char[] {','};
// символ
string[] fields;
// строка [] поля;
fields = selected.Split(sep);
// поля = выбранное, разбить;
currHotel = new HotelListltem();
currHotel.City = fields[0];
// Город = поля [О];
currHotel.HotelName = fields[1];
// поля [1]
currHotel.NumberRooms = Convert.Tolnt32(fields[2]);
// поля [2]
currHotel.Rate = Convert.ToDecimal(fields[3]);
// поля [3]
}
else
{
currHotel.HotelName = "";
}
}
Поскольку в списке элементов элементы хранятся в виде объектных ссылок, мы выполняем приведение типа выбранного элемента к типу string (Строка). Для того чтобы выделить значения полей, разделенные запятыми, используется метод String. Split (Строка.Разбиение), затем значения сохраняются в массиве строк fields (поля). Из массива эти значения переносятся в currHotel, где они и хранятся. В предыдущем разделе мы использовали currHotel для инициализации диалоговых окон New Hotel (Новая гостиница) и Change Hotel Information (Изменение информации о гостинице).
с помощью классов Windows FormsВ этой главе мы рассмотрели создание графических пользовательских интерфейсов с помощью классов Windows Forms (Формы Windows) из .NET Framework. Сперва мы рассмотрели основные принципы, и научились создавать с помощью .NET Framework простые Windows-приложения с самого начала, без использования каких-либо специальных средств. Рисование выполняется в переопределенном методе OnPaint с помощью шрифта и кисти. Для управления взаимодействием пользователя с программой используется механизм обработки событий .NET. Он применяется, например, для обработки событий мыши и клавиатуры. Управляющие элементы намного упрощают программирование Windows-приложений. Управляющий элемент меню упрощает процесс добавления меню к Windows-программе. Visual Studio.NET также намного упрощает процесс программирования Windows-приложений. К сожалению, в C++ не поддерживается конструктор форм (Forms Designer). Зато с помощью конструктора форм (Forms Designer) можно очень быстро создать проект на С#, который, при желании, можно перенести в проект на C++. Конструктор форм (Forms Designer) позволяет перетаскивать управляющие элементы с инструментальной панели (Toolbox) на форму и потом в режиме Design (Конструктор) определять свойства этих управляющих элементов. Можно также без труда добавить в приложение обработчики событий. Диалоговое окно — это особый вид формы, с помощью свойств которого можно реализовать обмен информацией между родительской формой и диалоговым окном. Управляющий элемент ListBox (Список элементов) упрощает процесс отображения списков. В заключение мы разработали графический пользовательский интерфейс для программы Acme Travel Agency (бюро путешествий Acme). |